/* ******************************************************************************
 *  BOARD.HH
 * ******************************************************************************/

/* *
 * Copyright (C) 2005 Atul S. Vasu
 *
 * This program is free software; you cn redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 * */

/* *
 * Contact Details:
 *
 * mail -
 *  Atul S. Vasu, Flat No. 3, Govt Quarters, Kowdiar,
 *                Thiruvananthapuram, Kerala, India. 695003.
 * email - atulsvasu@gmail.com
 *        - atulsv@cse.iitm.ernet.in (till early 2007).
 * */
#ifndef __BOARD_H_
#define __BOARD_H_

//For memcpy.
#ifndef _SINGLE_
#include <cstring>
#endif

/// Type of chess pieces.
/**
 * There are 6 basic type of chess pieces. They
 * are pawn, bishop, knight, rook, queen, king.
 * To store the board easily we augment the
 * colour also with the type. Including the
 * requirement to store the empty square, we
 * have a fictitious piece `empty'.
 */
enum e_piece{
  EMPTY, WPAWN, WBISHOP, WKNIGHT, WROOK, WQUEEN, WKING,
  BPAWN, BBISHOP, BKNIGHT, BROOK, BQUEEN, BKING, BIGPIECE
};
/// piece stores e_piece. Unfortunately, they are not identical.
/**
 * This typedef is quite unneccessary, had C++ committee recommended
 * unsigned char for enum's. Again enum is too big for me.
 */
typedef unsigned char piece;
/// Colour of chess piece.
/**
 * Apart from White and Black, the None is included for
 * the purpose of the colour of EMPTY square.
 */
enum e_colour {
  NONE, WHITE, BLACK
};
typedef unsigned char colour;
/// Returns of given piece.
/**
 * It maps a piece to its corresponding colour.
 * Implementation is near optimal. May be improved
 * slightly by division. But it loses clarity.
 * further as N.S. Narayanaswamy noted, switch case
 * is really really fast due to hashing. And as
 * the enum is ordered exactly as it is, g++ can
 * be quite good in implementing it.
 */
colour colour_of(const piece& p) {
  switch(p)
    {
    case EMPTY: return NONE;
    case WPAWN: case WBISHOP: case WKNIGHT:
    case WROOK: case WQUEEN: case WKING: return WHITE;
    case BPAWN: case BBISHOP: case BKNIGHT:
    case BROOK: case BQUEEN: case BKING: return BLACK;
    }
  return NONE;
}

/// Dimension of chess board
/**
 * It is used for symbollic purposes only. Do not
 * change its value. The behaviour is supposedly
 * catastrophic.
 */
const int n=8;

/// Noman-clature of a cell.
/**
 * Used for indexing the chess board. OUT is
 * always an invalid position.
 */
enum e_cell{
  A1, B1, C1, D1, E1, F1, G1, H1,
  A2, B2, C2, D2, E2, F2, G2, H2,
  A3, B3, C3, D3, E3, F3, G3, H3,
  A4, B4, C4, D4, E4, F4, G4, H4,
  A5, B5, C5, D5, E5, F5, G5, H5,
  A6, B6, C6, D6, E6, F6, G6, H6,
  A7, B7, C7, D7, E7, F7, G7, H7,
  A8, B8, C8, D8, E8, F8, G8, H8,OUT
} ;

//
// NOTE:
//      FILE ranges from 0 to n-1 from left to right unlike the standard 1 to 8.
//      RANK ranges from 0 to n-1 from down to up unlike the standard 1 to 8.
#define FILE(x) x%n
#define RANK(x) x/n

typedef unsigned char cell;

/// Initial Chess Board for a valid game.
/**
 * It is in the same order as that of the above
 * table. The order may not be modified. It is
 * assumed in many places.
 */
const piece init_pos[n*n]= {
  WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK,
  WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN,
  EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
  EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
  EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
  EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
  BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN,
  BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK
};

/// Stores the position.
/**
 * It stores no information other than the position of pieces in
 * the board. It doesn't store informations like whether king has
 * moved? or which is the ep-square? etc.
 */
class board {
  piece brd[n*n];///< Stores the current position in an array of size n x n.
public:
  /// Default Constructor.
  /**
   * Copies the initial position init_pos to the brd. As memory is
   * statically allocated it is not taken care of.
   */
  board() {
    std::memcpy(brd,init_pos,n*n);
  }
  /// Copy Constructor.
  /**
   * Copies using the memcpy function on the pointer brd. It is
   * found to be much faster than the std::copy()! May be g++
   * will make copy better by using the same method as memcpy.
   * But right now it is not.
   */
  board(const board& b) {
    std::memcpy(brd,b.brd,n*n);
  }
  /// Reset function.
  /**
   * Resets the board as to start afresh a game.
   */
  void reset() {
    std::memcpy(brd,init_pos,n*n);
  }
  /// Destructor.
  /**
   * This destructor currently has no job. May be removed.
   */
  ~board() {}

  /// Basic indexing facility.
  /**
   * To get a feal of indexing I used [], instead of the
   * more popular C++ style or ()
   */
  piece& operator [] (cell i) {
    return brd[i];
  }
  /// Indexing on const objects.
  /**
   * The piece returned cannot be modified. It is
   * considered whether const piece& or piece should be returned.
   * But I think g++ will auto-inline this resulting in faster
   * code than the traditional by definition copy mechanism.
   * In an older compiler, it is probably better to replace by
   * piece.
   */
  const piece& operator [] (cell i) const {
    return brd[i];
  }
};
/// Equal-To operator over for board
bool operator == (const board& b1, const board& b2) {
  for(int i=0;i<n*n;i++)
    if(b1[i]!=b2[i]) return false;
  return true;
}

/// Auxillary information on the game position.
/**
 * Chess position cannot be fully determined by the position of the
 * pieces, a variety of other stuff also be stored. Some few extra
 * things like time of last capture also need to be stored. But we
 * assume that all players generally resign in pathatic situations.
 *
 * It is stored as a seperate class, not as a part of position or
 * board, because delta (defined in engine.hh) uses aux_info alone.
 */
// Size of aux_info = 4+2+2+16+16 = 5 bytes.
struct aux_info {
  /// Castle-flags of both sides.
  /**
   * A castle is possible only if the corresponding square is
   * true. Initially every bools are true. Then it is changed
   * it a King or Rook moves. Note that a king move will disable
   * both sides, where as rook disables only the side it cares.
   * Note that if the rook is captured, then too the flag is
   * reset. This is to avoid the checking whether rook is present
   * at that position while castling.
   *
   * It is stored as a bit-field as it requires only one byte.
   */
  bool long_w:1, short_w:1, long_b:1, short_b:1;
  /// Whether castled or not.
  /**
   * Meant for evaluation purposes. Once castled it get an
   * advantage (or loss of penality).
   */
  bool castle_w:1, castle_b:1;
  /// Side to move
  /**
   * It is a very complex issue, that it could be stored in 2 bits.
   * It is due to the fact that enum is unsigned char for small collection,
   * Rather than the expected? char( which is by default signed, it is
   * deemed to be implementation dependent). If on porting the program some
   * bug occurs just remove the field length.
   */
  colour to_move:2;

  /// En-passant square of White and Black.
  /**
   * eps_w is the position obtained by a white pawn's move by a
   * double leap. It is the ``attackable'' position by black's
   * pawn. It is volatile and stays only for one move. When it
   * is invalid, the fact is signalled as a value of OUT.
   * Similarly for eps_b.
   */
  cell eps_w, eps_b;

  /// Position of both the Kings.
  /**
   * wk_pos is the position of the White King &
   * bk_pos is the position of the Black King.
   * It is stored for fast validation of moves.
   * We frequently have to check the position of the
   * king while checking whether it is under attack.
   * This is modified every time king makes its(his)
   * move.
   */
  cell wk_pos,bk_pos;
  /// Constructor.
  /**
   * Each of the member is initialized to a valid initial
   * condition of the chess game.
   */
  aux_info():long_w(true),short_w(true), long_b(true),short_b(true),
  castle_w(false), castle_b(false), to_move(WHITE), eps_w(OUT), eps_b(OUT),
  wk_pos(E1), bk_pos(E8) {}

  /// Reset Function.
  /**
   * Resets the auxillary information to start a new game, usually.
   */
  void reset() {
    long_w=short_w=long_b=short_b=true;
    castle_w=castle_b=false;
    to_move=WHITE;
    eps_w=eps_b=OUT;
    wk_pos=E1; bk_pos=E8;
  }
};
/// Equalto Operator for aux_info
bool operator == (const aux_info& b1, const aux_info& b2) {
  return b1.long_w==b2.long_w and b1.short_w==b2.short_w and b1.long_b==b2.long_b and b1.short_b==b2.short_b
    and b1.castle_w == b2.castle_w and b1.castle_b ==b2.castle_b and b1.to_move==b2.to_move and b1.eps_w==b2.eps_w
    and b1.eps_b==b2.eps_b and b1.wk_pos==b2.wk_pos and b1.bk_pos==b2.bk_pos;
}

/// Complete positional info:
/**
 * Position is complete only if both board and aux_info are combined.
 * This will be the struct used through out, for almost all purposes.
 * It is chosen to be struct, given visibility to member values, for
 * it is actually hidden by members essentially to the required level.
 */
struct position {
  board CB;///< Chess Board.
  aux_info A;///< Auxillary information.
  position():CB(),A() {}
  void reset() {
    CB.reset();
    A.reset();
  }
};

bool operator == (const position& p1, const position& p2) {
  return p1.CB==p2.CB and p1.A==p2.A;
}

#endif

// 1st July 2005.
// --- Implemented all basic features.
